package com.srwl.mytx.activity;

import android.Manifest;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.cjt2325.cameralibrary.util.ScreenUtils;
import com.srwl.mytx.R;
import com.srwl.mytx.RetrofitManager;
import com.srwl.mytx.domain.CommonResult;
import com.srwl.mytx.service.UserService;
import com.srwl.mytx.tao.av.CameraHelper;
import com.srwl.mytx.tao.av.ClipManager;
import com.srwl.mytx.tao.av.FileUtils;
import com.srwl.mytx.tao.av.SystemUtil;
import com.srwl.mytx.tao.av.VideoBean;
import com.srwl.mytx.utils.IMFileTools;
import com.srwl.mytx.utils.VideoUtil;
import com.srwl.mytx.widget.ConfirmDialog;
import com.srwl.mytx.widget.RecordTimelineView;
import com.umeng.analytics.MobclickAgent;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

//import com.im.Util;
//import com.im.av.logic.manage.IMCommitManager;
//import com.taobao.av.ui.view.recordline.ClipManager;
//import com.taobao.av.ui.view.recordline.VideoBean;
//import com.taobao.av.util.CameraHelper;
//import com.taobao.av.util.FileUtils;
//import com.taobao.av.util.SystemUtil;

public class VideoRecordActivity extends BaseActivity implements SurfaceHolder.Callback, View.OnClickListener {
    private static final String TAG = VideoRecordActivity.class.getSimpleName();
    private final int PERMISSION_REQUEST_CODE = 100; //权限申请请求码
    private static int REQUEST_CODE_VIDEO_PLAYER = 101;
    private boolean granted = false;
    private String path;
    private ImageView iv_back; //退出
    private ImageView iv_light; //闪光灯
    private ImageView iv_cameraChoose;// 摄像头选择

    private SurfaceView surfaceView; //显示摄像头预览画面
    private ImageView iv_recorder;  //录制按键
    private ImageView iv_recorPause; //录制暂停：实际上是停止录制，最后的完成录制的时候，是把几个录制的视频片段拼接成一个视频
    private CheckBox cb_deleteVideoClip;//删除最后一个视频片段
    private ImageView iv_commit; //完成视频录制确定按键
    private TextView tv_recordTime;
    private TextView tv_videoTooShort;
    private RecordTimelineView recordTimelineView;
    private ProgressBar progressBar;
    private SurfaceHolder surfaceHolder;
    private MediaRecorder mediaRecorder;
    private Camera camera;
    private Camera.Parameters parameters;

    private boolean isRecording;//标记是否增长录制
    private Handler mSafeHandler;
    private ClipManager mClipManager; //视频片段管理者，有删除片段等功能
    private int maxDuration = 20000;//视频录制最长时间 20s 视频差不多是2M多
    private int minDuration = 3000;
    private int currentDuration = 0;
    private StringBuilder mFormatBuilder;
    private Formatter mFormatter;
    private Runnable _runnableTimer;
    private long startTime;
    private int mVideoIndex = -1;//视频片段索引
    private String dir;//视频存储路径
    private Animation scaleAnimation;
    private Animation alpahAnimation;
    private Camera.Size optimalSize;//最优预览尺寸
    private long lastRecordClickTime;
    private int cameraPosition;
    private List<String> clipPaths = new ArrayList<>();

    //视频视频的尺寸
    private Camera.Size videoRecordSize;
    private int videoFrameRate = 30;
    private int handlerTime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_recorder);
        initView();
        initClipManager();
        alpahAnimation = AnimationUtils.loadAnimation(this, R.anim.taorecorder_alpha_reverse);
        scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.taorecorder_scale_reverse);

        cameraPosition = SystemUtil.getCameraFacingBack();//第一次开启后面的摄像头
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        mediaRecorder = new MediaRecorder();

        mFormatBuilder = new StringBuilder();
        mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
        initTimer();
        dir = this.getExternalCacheDir().getAbsolutePath() + File.separator + "short_video";
        File file = new File(dir);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    private void initTimer() {
        //本来我想在用Timer  TimerTask,但是考虑到TimerTask是非Ui线程，每次更新ui还得用handler,或者runOnUiThread,可能性能还不如这个Runnable，但是用Timer 逻辑更清晰，
        _runnableTimer = new Runnable() {
            public void run() {
                if (mediaRecorder != null) {
                    if (startTime == 0L && !isRecording) {
                        getSafeHandler().postDelayed(this, 25L);
                    } else {
                        if (startTime == 0L) {
                            startTime = System.currentTimeMillis();
                        }
                        long currentClipDuration = (System.currentTimeMillis() - startTime);
                        recordTimelineView.setDuration((int) currentClipDuration);//设置当前视频片段的长度
                        mClipManager.onRecordFrame(currentClipDuration);
                        setRecordTime();
                        if (mClipManager.isMinDurationReached()) {
                            iv_commit.setVisibility(View.VISIBLE);
                        }

                        if (mClipManager.isMaxDurationReached()) {
                            stopRecord();
                        } else {
                            getSafeHandler().postDelayed(this, 25L);
                        }
                    }
                }
            }
        };
    }

    /**
     * 初始化视频片段管理器
     */
    private void initClipManager() {
        mClipManager = new ClipManager();
        mClipManager.setMaxDuration(maxDuration);
        mClipManager.setMinDuration(minDuration);
    }

    private void initView() {
        iv_back = findViewById(R.id.iv_back);
        iv_light = findViewById(R.id.iv_light);
        iv_cameraChoose = findViewById(R.id.iv_camera_choose);
        surfaceView = findViewById(R.id.camera_view);
        iv_recorder = findViewById(R.id.iv_recorder);
        cb_deleteVideoClip = findViewById(R.id.btn_delete_last_clip);
        iv_recorPause = findViewById(R.id.iv_record_pause);
        iv_commit = findViewById(R.id.iv_commit);
        tv_videoTooShort = findViewById(R.id.tv_video_too_short);
        tv_videoTooShort.setAlpha(0f);
        tv_recordTime = findViewById(R.id.tv_record_time);
        progressBar = findViewById(R.id.progress_bar);
        recordTimelineView = findViewById(R.id.record_time_line);
        recordTimelineView.setMaxDuration(maxDuration);
        recordTimelineView.setMinDuration(minDuration);
        recordTimelineView.setColor(R.color.holo_red_light, R.color.yancy_indigo600, R.color.common_white, R.color.half_transparent_white);
        iv_back.setOnClickListener(this);
        iv_light.setOnClickListener(this);
        iv_cameraChoose.setOnClickListener(this);
        iv_recorder.setOnClickListener(this);
        cb_deleteVideoClip.setOnClickListener(this);
        iv_commit.setOnClickListener(this);
        surfaceView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        if (event.getPointerCount() == 1) {//一个手指点击
                            handleFocus(event.getX(), event.getY());
                        }
                        break;
                }

                return false;
            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_back:
                onBackPress();

                break;
            case R.id.iv_light:
                changeLight();

                break;
            case R.id.iv_camera_choose:
                rotateCamera();
                break;

            case R.id.iv_recorder:

                Long currentTime = System.currentTimeMillis();
                if (currentTime - lastRecordClickTime < 500) {//防止误击
                    return;
                }
                lastRecordClickTime = currentTime;
                if (isRecording) {
                    stopRecord();
                } else {
                    startRecord();
                }

                break;
            case R.id.btn_delete_last_clip:

                if (cb_deleteVideoClip.isChecked()) {//点一次，：显示最后一段视频被选中
                    recordTimelineView.selectLast();
                    cb_deleteVideoClip.setChecked(true);
                } else { //再点一次：删除
                    mClipManager.removeLastClip();
                    recordTimelineView.deleteLast();
                    cb_deleteVideoClip.setChecked(false);
                    cb_deleteVideoClip.setEnabled(mClipManager.isUnEmpty());
                    int totalRecordTime = mClipManager.getDuration();
                    if (totalRecordTime < minDuration) {
                        iv_commit.setVisibility(View.GONE);
                    }
                    setRecordTime();
                    clipPaths.remove(mVideoIndex);
                    mVideoIndex--;
                    if (mVideoIndex == -1) {//如果视频片段全部删完了，则显示摄像头切换图标
                        iv_cameraChoose.setVisibility(View.VISIBLE);
                    }
                }
                break;
            case R.id.iv_commit:
                toIMPlayRecordVideoActivity();

        }
    }

    private void showProgressBar() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressBar.setVisibility(View.VISIBLE);
            }
        });
    }

    private void hideProgressBar() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressBar.setVisibility(View.GONE);
            }
        });
    }

    /**
     * 显示界面上的录像时间
     */
    private void setRecordTime() {
        int totaltime = mClipManager.getDuration();

        if (totaltime >= 0 && totaltime < maxDuration) {
            mFormatBuilder.setLength(0);
            String stime = mFormatter.format("%d.%d 秒", totaltime / 1000, totaltime / 100 % 10).toString();
            tv_recordTime.setText(stime);
        }

    }

    //闪光灯设置切换
    private void changeLight() {
        Camera.Parameters parameters = camera.getParameters();
        if (CameraHelper.getFlashlightOn(parameters)) {
            CameraHelper.setFlashlightMode(parameters, false);
            iv_light.setImageResource(R.drawable.aliwx_sv_wx_shiny_nor);
        } else {
            CameraHelper.setFlashlightMode(parameters, true);
            iv_light.setImageResource(R.drawable.aliwx_sv_wx_shiny_pre);
        }

        camera.setParameters(parameters);
    }

    private void rotateCamera() {
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        int cameraCount = Camera.getNumberOfCameras();

        for (int i = 0; i < cameraCount; ++i) {
            Camera.getCameraInfo(i, cameraInfo);
            if (cameraPosition == SystemUtil.getCameraFacingBack()) {
                if (cameraInfo.facing == SystemUtil.getCameraFacingFront()) {
                    relaeaseCamera();
                    cameraPosition = SystemUtil.getCameraFacingFront();
                    startPreview();
                    iv_light.setVisibility(View.INVISIBLE);
                    iv_cameraChoose.setImageResource(R.drawable.aliwx_sv_wx_camera_pre);

                    break;
                }
            } else if (cameraInfo.facing == SystemUtil.getCameraFacingBack()) {

                relaeaseCamera();
                cameraPosition = SystemUtil.getCameraFacingBack();
                startPreview();
                iv_light.setImageResource(R.drawable.aliwx_sv_wx_shiny_nor);
                iv_cameraChoose.setImageResource(R.drawable.aliwx_sv_wx_camera_nor);
                break;
            }
        }

    }

    /**
     * 释放Camera
     */
    private void relaeaseCamera() {
//        if (surfaceHolder != null) {
//            surfaceHolder.removeCallback(this);
//        }
        if (camera != null) {
            camera.stopPreview();
            try {
                camera.setPreviewDisplay(null);
            } catch (IOException e) {
                e.printStackTrace();
            }
            camera.release();
            camera = null;
        }
    }

    public boolean checkIsUnSupportFlishLight(Camera camera) {

//        return Util.hasFlash(camera);
        // TODO: 2019/7/9 后续判断手机是否有闪光灯
        return false;
    }

    private void relaeaseMediaRecorder() {
        if (mediaRecorder != null) {
            mediaRecorder.release();
            mediaRecorder = null;
        }

    }

    public void startRecord() {

        iv_recorder.startAnimation(alpahAnimation);//显示呼吸效果动画
        iv_recorPause.setVisibility(View.VISIBLE);//显示暂停图标
        iv_commit.setEnabled(false);//录制过程中禁用 提交按键
        iv_cameraChoose.setVisibility(View.INVISIBLE);//一旦开始录制，就一直隐藏切换摄像头图标，因为前后摄像头录制的视频方向不一致，合并处理的视频，方向有问题，
        cb_deleteVideoClip.setVisibility(View.VISIBLE);
        cb_deleteVideoClip.setEnabled(false);
        cb_deleteVideoClip.setChecked(false);
        //每次开始录像，生成一个VideoBean，添加进ClipManager
        VideoBean vb = new VideoBean();
        mVideoIndex++;//每录制一段视频，索引增加一次，
        String clipPath = dir + File.separator + getLastOutputFileName();
        vb.videoFile = clipPath;
        mClipManager.onRecordStarted(vb);
        clipPaths.add(clipPath);
        //重置录像的开始时间点
        startTime = 0L;
        //开始记录录像时间
        getSafeHandler().post(_runnableTimer);

        setUpMediaRecorder();
        isRecording = true;
    }

    private String getLastOutputFileName() {
        return "temp_" + mVideoIndex + ".mp4";
    }

    private void setUpMediaRecorder() {
        CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
        Log.d(TAG, "QUALITY_480P对应参数，videoBitRate:" + mProfile.videoBitRate + "   videoFrameHeight:" + mProfile.videoFrameRate + "   videoFrameWidth:" + mProfile.videoFrameWidth + "   videoFrameHeight:" + mProfile.videoFrameHeight);
        camera.unlock();
        mediaRecorder.setCamera(camera);
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mediaRecorder.setVideoSize(videoRecordSize.width, videoRecordSize.height);
        Log.i(TAG, "setUpMediaRecorder: VideoSize: 宽" + videoRecordSize.width + "高：" + videoRecordSize.height);
        //  mediaRecorder.setVideoSize(1280, 720);
        mediaRecorder.setVideoFrameRate(24);
        mediaRecorder.setVideoEncodingBitRate(2000000);
        if (cameraPosition == SystemUtil.getCameraFacingFront()) {
            mediaRecorder.setOrientationHint(270);
        } else {
            mediaRecorder.setOrientationHint(90);//设置OrientationHint，只是标记一个视频方向，以便播放器识别视频方向，并不是真的对视频源做了旋转操作
        }


        mediaRecorder.setOutputFile(dir + File.separator + getLastOutputFileName());
        mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());

        try {
            mediaRecorder.prepare();
            mediaRecorder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void stopRecord() {
        if (maxDuration - mClipManager.getDuration() < 1000 && maxDuration - mClipManager.getDuration() > 100) {//如果停止的时间点与最大录制时间只差1s，那就让它录制到最大录制时间
            return;
        } else if (maxDuration - mClipManager.getDuration() < 100) {//禁用录制按键
            iv_recorder.setEnabled(false);
            iv_recorder.setAlpha(0.5f);
        }
        iv_commit.setEnabled(true);
        // iv_cameraChoose.setVisibility(View.VISIBLE); //一旦录制一次后，就禁用切换摄像头，因为前后摄像头录制的视频合并处理，方向有问题，
        iv_recorder.clearAnimation();//清除动画
        iv_recorPause.setVisibility(View.INVISIBLE);//隐藏暂停图标
        mClipManager.onRecordPaused();
        if (mSafeHandler != null) {
            getSafeHandler().removeCallbacks(_runnableTimer);
        }
        if (System.currentTimeMillis() - startTime < 1000) {//录制时间小于1S 丢弃,因为MediaRecorder 录制时间太短就停止录制会奔溃，找不到原因，所以当录制时间小于1s的时间，直接重置MediaRecorder
            mClipManager.removeLastClip();//把最后一条视频片段删除
            recordTimelineView.setDuration(0);//设置当前视频片段的长度为0
            setRecordTime();//重新设置拍摄进度
            mediaRecorder.reset();//重置MediaRecorder
            clipPaths.remove(mVideoIndex);//清除当前视频片段的地址记录
            mVideoIndex--;
            ObjectAnimator animator_txt_tip = ObjectAnimator.ofFloat(tv_videoTooShort, "alpha", 1f, 0f);
            animator_txt_tip.setDuration(2000);
            animator_txt_tip.start();
        } else {
            recordTimelineView.clipComplete();
            mediaRecorder.setPreviewDisplay(null);
            mediaRecorder.stop();
            mediaRecorder.reset();
            String targetPath = mClipManager.getClip(mVideoIndex).videoFile;
            final String outPutPath = targetPath.replace(".mp4", System.currentTimeMillis() + ".mp4");
            //   String[] command = new String[]{"-i" , targetPath,"-metadata:s:v","rotate=\"180\"", outPutPath }; //这个命令只是修改rotate 的值，就是修改OrientationHint的值，


        }
        cb_deleteVideoClip.setEnabled(mClipManager.isUnEmpty());
        isRecording = false;
    }

    private Handler getSafeHandler() {
        if (mSafeHandler != null) {
            return mSafeHandler;
        } else {
            mSafeHandler = new Handler();
            return mSafeHandler;
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        //全屏显示
        if (Build.VERSION.SDK_INT >= 19) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        } else {
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(option);
        }
        //  getPermissions();
    }

    /**
     * 获取权限
     */
    private void getPermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                //具有权限
                granted = true;
            } else {
                //不具有获取权限，需要进行权限申请
                ActivityCompat.requestPermissions(this, new String[]{
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE);
                granted = false;
            }
        }
    }

    @TargetApi(23)
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            int size = 0;
            if (grantResults.length >= 1) {
                int writeResult = grantResults[0];
                //读写内存权限
                boolean writeGranted = writeResult == PackageManager.PERMISSION_GRANTED;//读写内存权限
                if (!writeGranted) {
                    size++;
                }
                //录音权限
                int recordPermissionResult = grantResults[1];
                boolean recordPermissionGranted = recordPermissionResult == PackageManager.PERMISSION_GRANTED;
                if (!recordPermissionGranted) {
                    size++;
                }
                //相机权限
                int cameraPermissionResult = grantResults[2];
                boolean cameraPermissionGranted = cameraPermissionResult == PackageManager.PERMISSION_GRANTED;
                if (!cameraPermissionGranted) {
                    size++;
                }
                if (size == 0) {
                    granted = true;

                } else {
                    showToast("请到设置-权限管理中开启");
                    finish();
                }
            }
        }
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.d(TAG, "surfaceCreated执行了");
        startPreview();

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.d(TAG, "surfaceChanged:" + width + "    " + height);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.d(TAG, "surfaceDestroyed执行了");
        relaeaseCamera();
    }

    private void startPreview() {
        camera = Camera.open(cameraPosition);

        camera.setDisplayOrientation(90);
        try {
            camera.setPreviewDisplay(surfaceHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }
        parameters = camera.getParameters();
        List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
        List<Camera.Size> videoSizes = parameters.getSupportedVideoSizes();
        List<int[]> supportedPreviewFpsRange = parameters.getSupportedPreviewFpsRange();
        videoFrameRate = generateVideoFrameRate(supportedPreviewFpsRange);
        videoRecordSize = getSupportedVideoSizes(videoSizes);
        optimalSize = getOptimalVideoSize_new(previewSizes, surfaceView.getWidth(), surfaceView.getHeight());
        Map<String, Object> video_record = new HashMap<String, Object>();
        video_record.put("width", optimalSize.width);
        video_record.put("height", optimalSize.height);
        MobclickAgent.onEventObject(VideoRecordActivity.this, "video_record", video_record);
        Map<String, Object> phoneInfo = new HashMap<>();
        phoneInfo.put("brand", com.srwl.mytx.utils.SystemUtil.getDeviceBrand());
        phoneInfo.put("model", com.srwl.mytx.utils.SystemUtil.getSystemModel());
        phoneInfo.put("version", com.srwl.mytx.utils.SystemUtil.getSystemVersion());
        Map<String, Object> logRecord = new HashMap<>();
        logRecord.put("phoneInfo", phoneInfo);
        logRecord.put("optimalSize", optimalSize);
        logRecord.put("previewSizes", previewSizes);
        Map<String, Object> surfaceViewSize = new HashMap<>();
        surfaceViewSize.put("width", surfaceView.getWidth());
        surfaceViewSize.put("height", surfaceView.getHeight());
        logRecord.put("surfaceViewSize", surfaceViewSize);
        logRecord.put("videoSizes", videoSizes);
        uploadLogData(logRecord);
        Log.d(TAG, "最优尺寸：" + optimalSize.width + "  " + optimalSize.height);
        parameters.setPreviewSize(optimalSize.width, optimalSize.height);
        parameters.set("orientation", "portrait");
        List<String> focusModes = parameters.getSupportedFocusModes();
        //设置自动对焦模式
        if (focusModes.contains("continuous-video")) {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);

        }
        if (checkIsUnSupportFlishLight(camera)) {//如果不支持闪光灯，就隐藏闪光灯切换图标
            iv_light.setVisibility(View.VISIBLE);
        }
        //缩短Recording启动时间
        parameters.setRecordingHint(true);

        //影像稳定能力
        if (parameters.isVideoStabilizationSupported())
            parameters.setVideoStabilization(true);
        camera.setParameters(parameters);
        camera.startPreview();
    }

    private int generateVideoFrameRate(List<int[]> supportedPreviewFpsRange) {
        int frameRate = 30;
//        for (int[] ints : supportedPreviewFpsRange) {
//            Log.d(TAG, "generateVideoFrameRate: min: " + ints[0] + " max: " + ints[1]);
//            if (ints[0] == 30000 || ints[1] == 30000) {
//                frameRate = 30;
//                break;
//            } else if (ints[0] == 24000 || ints[1] == 24000) {
//                frameRate = 24;
//                break;
//            } else if (ints[0] == 20000 || ints[1] == 20000) {
//                frameRate = 20;
//                break;
//            } else if (ints[0] == 15000 || ints[1] == 15000) {
//                frameRate = 15;
//                break;
//            } else if (ints[0] == 7000) {
//                frameRate = 7;
//                break;
//            }
//
//        }

        for (int i = supportedPreviewFpsRange.size() - 1; i >= 0; i--) {
            int[] ints = supportedPreviewFpsRange.get(i);
            Log.d(TAG, "generateVideoFrameRate: min: " + ints[0] + " max: " + ints[1]);
            if (ints[0] == 30000 || ints[1] == 30000) {
                frameRate = 30;
                break;
            } else if (ints[0] == 24000 || ints[1] == 24000) {
                frameRate = 24;
                break;
            } else if (ints[0] == 20000 || ints[1] == 20000) {
                frameRate = 20;
                break;
            } else if (ints[0] == 15000 || ints[1] == 15000) {
                frameRate = 15;
                break;
            } else if (ints[0] == 7000) {
                frameRate = 7;
                break;
            }
        }
        return frameRate;
    }

    private Camera.Size getSupportedVideoSizes(List<Camera.Size> supportedVideoSizes) {

        for (Camera.Size supportedVideoSize : supportedVideoSizes) {
            Log.d(TAG, "getSupportedVideoSizes: with:" + supportedVideoSize.width + "   height:" + supportedVideoSize.height);
            if (supportedVideoSize.width == 1280 && supportedVideoSize.height == 720) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 864) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 800) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 720) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 640) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 480) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 352) {
                return supportedVideoSize;
            }
        }

        return supportedVideoSizes.get(0);
    }

    /**
     * 同时从 分辨率高宽比和像素点面积两个维度来判断各个预览分辨率与目标分辨率的差别
     * 差别最小的，作为预览分辨率
     * 经过但愿测试 非常科学
     *
     * @param previewSizes
     * @param surfaceViewWidth
     * @param surfaceViewHeight
     * @return
     */
    private Camera.Size getOptimalVideoSize_new(List<Camera.Size> previewSizes, int surfaceViewWidth, int surfaceViewHeight) {
        Camera.Size previewSize = null;
        double totalDifference = Double.MAX_VALUE;
        double targetRatio = (double) surfaceViewHeight / surfaceViewWidth;
        Log.i(TAG, "getOptimalVideoSize_new: targetRatio :" + targetRatio);
        long targetArea = surfaceViewWidth * surfaceViewHeight;
        Log.i(TAG, "getOptimalVideoSize_new: targetArea :" + targetArea);
        for (int i = 0; i < previewSizes.size(); i++) {
            double ratio = ((double) previewSizes.get(i).width) / previewSizes.get(i).height;
            double ratioDifference = Math.abs(ratio - targetRatio);
            Camera.Size size = previewSizes.get(i);
            long area = size.width * previewSizes.get(i).height;
            double areaDifference = (double) Math.abs(area - targetArea) / targetArea;
            double currentTotalDifference = ratioDifference + areaDifference;
            //计算方差,估计叫 方差 ，表示数据的离散程度，我们希望找到 在面积、高宽比都与期望值比较接近的，而不是一个完全一样，一个相去甚远，好比是寻找学生中 成绩总体不错的，而不是要 偏科生。
            double variance = (Math.pow((Math.abs(ratioDifference - currentTotalDifference / 2)), 2) + Math.pow((Math.abs(areaDifference - currentTotalDifference / 2)), 2)) / 2;
            Log.i(TAG, "getOptimalVideoSize_new: variance :" + variance);
            currentTotalDifference = currentTotalDifference + variance;
            Log.i(TAG, "getOptimalVideoSize_new: currentTotalDifference :" + currentTotalDifference + " size.width:" + size.width + "  size.height:" + size.height);
            if (currentTotalDifference < totalDifference) {
                totalDifference = currentTotalDifference;
                previewSize = size;
            }
        }
        return previewSize;
    }


    private Camera.Size getOptimalVideoSize(List<Camera.Size> previewSizes, int surfaceViewWidth, int surfaceViewHeight) {
        Camera.Size previewSize = null;
        List<Camera.Size> sizes = new ArrayList<>();
        //计算预览窗口高宽比，高宽比，高宽比
        //注意 是高/宽，因为对于摄像头来说，屏幕更长的一边，是宽，和android 里面view 的高宽是相反的
        float ratio = ((float) surfaceViewHeight / surfaceViewWidth);
        //首先选取宽高比与预览窗口高宽比一致且最大的输出尺寸
        for (int i = 0; i < previewSizes.size(); i++) {
            if (((float) previewSizes.get(i).width) / previewSizes.get(i).height == ratio) {
                sizes.add(previewSizes.get(i));
            }
        }
        if (sizes.size() > 0) {

            previewSize = Collections.max(sizes, new CompareSizesByArea());
            return previewSize;
        }
        //如果不存在宽高比与预览窗口高宽比一致的输出尺寸，则选择与其高宽比最接近的输出尺寸
        sizes.clear();
        float detRatioMin = Float.MAX_VALUE;
        for (int i = 0; i < previewSizes.size(); i++) {
            Camera.Size size = previewSizes.get(i);
            float curRatio = (float) size.width / size.height;
            if (Math.abs(curRatio - ratio) < detRatioMin) {
                detRatioMin = curRatio;
                previewSize = size;
            }
        }
        if (previewSize != null && previewSize.width * previewSize.height > 720 * 480) {

            Log.d(TAG, "updateCameraPreviewWithVideoMode: 最佳预览尺寸：" + previewSize.toString());
            return previewSize;
        }
        //如果宽高比最接近的输出尺寸太小，则选择与预览窗口面积最接近的输出尺寸
        long area = surfaceViewWidth * surfaceViewHeight;
        long detAreaMin = Long.MAX_VALUE;
        for (int i = 0; i < previewSizes.size(); i++) {
            Camera.Size size = previewSizes.get(i);
            long curArea = size.width * size.height;
            if (Math.abs(curArea - area) < detAreaMin) {
                detAreaMin = curArea;
                previewSize = size;
            }
        }
        Log.d(TAG, "updateCameraPreviewWithVideoMode: 最佳预览尺寸：" + previewSize.toString());
        return previewSize;
    }


    private Camera.Size getOptimalVideoSize(List<Camera.Size> supportedVideoSizes,
                                            List<Camera.Size> previewSizes, int w, int h) {
// Use a very small tolerance because we want an exact match.
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;

// Supported video sizes list might be null, it means that we are allowed to use the preview
// sizes
        List<Camera.Size> videoSizes;
        if (supportedVideoSizes != null) {
            videoSizes = supportedVideoSizes;
        } else {
            videoSizes = previewSizes;
        }
        Camera.Size optimalSize = null;

// Start with max value and refine as we iterate over available video sizes. This is the
// minimum difference between view and camera height.
        double minDiff = Double.MAX_VALUE;

// Target view height
        int targetHeight = h;

// Try to find a video size that matches aspect ratio and the target view size.
// Iterate over all available sizes and pick the largest size that can fit in the view and
// still maintain the aspect ratio.
        for (Camera.Size size : videoSizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                continue;
            if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

// Cannot find video size that matches the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : videoSizes) {
                if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    /**
     * 合并视频
     */
    private void toIMPlayRecordVideoActivity() {


        (new Thread(new Runnable() {
            public void run() {
                //  String[] input = new String[mVideoIndex];
                //  StringBuilder param = new StringBuilder();

//                for (int i = 0; i < mVideoIndex; ++i) {
//                    //  input[i] = dir + File.separator + "temp_" + i + ".mp4";
//                    //  videoPathList.add(dir + File.separator + "temp_" + i + ".mp4");
//
//                        param.append("file  '"+ dir + File.separator + "temp_" + i + ".mp4' \r\n");
//
//                }

//                for (String clipPath : clipPaths) {
//                    param.append("file  '" + clipPath + "' \r\n");
//                }

                showProgressBar();
                final String tempVideoPath = dir + File.separator + "temp_output.mp4";
                final String rotateVideoPath = dir + File.separator + "temp_rotate_output.mp4";

                FileUtils.deleteFile(tempVideoPath);
                //合并视频片段
                // MediaEncoderMgr.mergeMp4Files(input, tempVideoPath); // 阿里VideoSDK 有问题，全部是后摄像头拍摄的视频情况下，方向也不对，
                VideoUtil.appendMp4List(clipPaths, tempVideoPath);//mp4parser 当视频的方向信息不一致时候，有问题，就是前后摄像头都录制了视频片段的时候，播放的时候，有的就是倒立的了，
                toPlayerActivity(tempVideoPath);

                int size = 0;
                if ((new File(tempVideoPath)).isFile()) {
                    File file = new File(tempVideoPath);
                    size = (int) file.length();
                    Log.i(TAG, "run: 视频大小： " + size);
                }
                //----------------------------------------------------------------
                //处理速度太慢，放弃，，
//                String[] command;
//                if (cameraPosition == SystemUtil.getCameraFacingFront()) {//如果是前摄像头拍摄的视频，
//                    command = new String[]{"-i", tempVideoPath, "-vf", "transpose=0", rotateVideoPath};//transpose=0, 逆时针旋转90°，并水平翻转
//                } else {
//                    command = new String[]{"-i", tempVideoPath, "-vf", "transpose=1", rotateVideoPath};//transpose=1：顺时针旋转90°
//
//                }
//
//                FFmpeg ffmpeg = FFmpeg.getInstance(VideoRecordActivity.this);
//                try {
//                    ffmpeg.execute(command, new FFmpegExecuteResponseHandler() {
//                        @Override
//                        public void onSuccess(String message) {
//                            Log.d(TAG, "旋转视频成功" + message);
//                            toPlayerActivity(rotateVideoPath);
//                        }
//
//                        @Override
//                        public void onProgress(String message) {
//                            Log.d(TAG, "FFmpeg旋转视频执行中。。。。。。。。。。");
//                        }
//
//                        @Override
//                        public void onFailure(String message) {
//                            Log.e(TAG, "FFmpeg旋转视频失败" + message);
//                        }
//
//                        @Override
//                        public void onStart() {
//                            Log.d(TAG, "FFmpeg旋转视频开始");
//                        }
//
//                        @Override
//                        public void onFinish() {
//                            Log.d(TAG, "FFmpeg旋转视频结束");
//                        }
//                    });
//                } catch (FFmpegCommandAlreadyRunningException e) {
//                    e.printStackTrace();
//                }
//------------------------------------------------------------------------------

                //ffmpeg -i "concat:input1.mpg|input2.mpg|input3.mpg" -c copy output.mpg

                //通过FFmpeg 合并视频
//                String sourcePath = dir + File.separator + "temp_source_path.txt";
//                TextUtil.createText(sourcePath, param.toString());
//                String[] cmd = {"-f", "concat", "-safe", "0", "-i", sourcePath, "-c", "copy", tempVideoPath};
//                FFmpeg ffmpeg = FFmpeg.getInstance(VideoRecordActivity.this);
//                try {
//                    ffmpeg.execute(cmd, new FFmpegExecuteResponseHandler() {
//                        @Override
//                        public void onSuccess(String message) {
//                            Log.d(TAG, "合并视频成功" + message);
//                            toPlayerActivity(tempVideoPath);
//                        }
//
//                        @Override
//                        public void onProgress(String message) {
//                            Log.d(TAG, "FFmpeg合并视频执行中。。。。。。。。。。");
//                        }
//
//                        @Override
//                        public void onFailure(String message) {
//                            Log.e(TAG, "FFmpeg合并视频失败" + message);
//                        }
//
//                        @Override
//                        public void onStart() {
//                            Log.d(TAG, "FFmpeg合并视频开始");
//                        }
//
//                        @Override
//                        public void onFinish() {
//                            Log.d(TAG, "FFmpeg合并视频结束");
//                        }
//                    });
//                } catch (FFmpegCommandAlreadyRunningException e) {
//                    e.printStackTrace();
//                }
                //   toPlayerActivity(tempVideoPath);
            }
        })).start();
    }

    private void toPlayerActivity(String tempVideoPath) {
        String UUIDString = UUID.randomUUID().toString().replaceAll("-", "");
       // final String targetVideoPath = dir + File.separator + UUIDString + "_output.mp4";
      //  final String targetJpgPath = dir + File.separator + UUIDString + "_output.jpg";
        //  Bitmap thumbnailBitmap = ThumbnailUtils.createVideoThumbnail(tempVideoPath, MediaStore.Video.Thumbnails.MICRO_KIND);//生成封面缩微图
       // Bitmap thumbnailBitmap = getVideoThumb(tempVideoPath);
      // IMFileTools.writeBitmap(targetJpgPath, thumbnailBitmap, 100);
        //复制文件
        //  FileUtils.copyFile(jpegPath, targetJpgPath);
        //FileUtils.copyFile(tempVideoPath, targetVideoPath);
        hideProgressBar();
        getSafeHandler().post(new Runnable() {
            public void run() {

                // Bundle bundle = getIntent().getExtras();
                Bundle bundle = new Bundle();
                BigDecimal duration = new BigDecimal(mClipManager.getDuration());
                BigDecimal ms = new BigDecimal(1000);
                int returnValue = duration.divide(ms, 0, 1).intValue();
                bundle.putInt("videoDuration", returnValue);


                BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
                decodeOptions.inJustDecodeBounds = true;
               // BitmapFactory.decodeFile(targetJpgPath, decodeOptions);
              //  int actualWidth = decodeOptions.outWidth;
              //  int actualHeight = decodeOptions.outHeight;


//                int size = 0;
//                if ((new File(targetVideoPath)).isFile()) {
//                    File file = new File(targetVideoPath);
//                    size = (int) file.length();
//                }

               // bundle.putInt("framePicWidth", actualWidth);
               // bundle.putInt("framePicHeight", actualHeight);
                //bundle.putInt("videoSize", size);
                // IMCommitManager.commitEvent("Finish_Record", "Page_WangXin_VideoRecord", (long) mClipManager.getDuration(), "size", Integer.toString(size));
                bundle.putCharSequence("videoPath", tempVideoPath);
                //bundle.putCharSequence("framePicPath", targetJpgPath);
                //bundle.putCharSequence("uploadID", getIntent().getStringExtra("uploadID"));
                //bundle.putCharSequence("uploadTarget", getIntent().getStringExtra("uploadTarget"));

                Intent intent = new Intent(VideoRecordActivity.this, VideoCoverSelectActivity.class);
                intent.putExtras(bundle);
                // intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);//跳转到MyVideoPlayActivity后，不能finish本activity,因为用户可能返回来继续编辑
                startActivityForResult(intent, REQUEST_CODE_VIDEO_PLAYER);
                overridePendingTransition(R.anim.taorecorder_push_left_in, R.anim.taorecorder_push_left_out);
                //   finish();

            }
        });
    }

    private Bitmap getVideoThumb(String path) {
        MediaMetadataRetriever media = new MediaMetadataRetriever();
        media.setDataSource(path);
        return media.getFrameAtTime();
    }


    @Override
    protected void onPause() {
        super.onPause();
        if (isRecording) {
            stopRecord();
        }


    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        relaeaseMediaRecorder();
        if (alpahAnimation != null) {
            alpahAnimation.cancel();
            alpahAnimation.reset();
            alpahAnimation = null;
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            onBackPress();
            return true;

        } else {
            return super.onKeyDown(keyCode, event);
        }
    }

    private void onBackPress() {
        if (isRecording) {
            return;
        }
        if (mClipManager.isUnEmpty()) {
            ConfirmDialog dialog = new ConfirmDialog(this, "提醒", "确定放弃已经录制的视频?", true);
            dialog.show();
            dialog.setConfirmListener(new ConfirmDialog.ConfirmListener() {
                @Override
                public void confirm() {
                    FileUtils.clearTempFiles(dir);
                    finish();
                }
            });
        } else {
            finish();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (REQUEST_CODE_VIDEO_PLAYER == requestCode) {
            if (RESULT_OK == resultCode) {
                setResult(RESULT_OK, data);
                finish();
            }
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);

    }

    public void handleFocus(final float x, final float y) {
        if (camera == null) {
            return;
        }
        final Camera.Parameters params = camera.getParameters();
        Rect focusRect = calculateTapArea(x, y, 1f, this);
        camera.cancelAutoFocus();
        if (params.getMaxNumFocusAreas() > 0) {
            List<Camera.Area> focusAreas = new ArrayList<>();
            focusAreas.add(new Camera.Area(focusRect, 800));
            params.setFocusAreas(focusAreas);
        } else {
            Log.i(TAG, "focus areas not supported");
            //callback.focusSuccess();
            return;
        }
        final String currentFocusMode = params.getFocusMode();
        try {
            params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            camera.setParameters(params);
            camera.autoFocus(new Camera.AutoFocusCallback() {
                @Override
                public void onAutoFocus(boolean success, Camera camera) {
                    if (success || handlerTime > 10) {
                        Camera.Parameters params = camera.getParameters();
                        params.setFocusMode(currentFocusMode);
                        camera.setParameters(params);
                        // camera.autoFocus(null);
                        handlerTime = 0;
                        // callback.focusSuccess();
                    } else {
                        handlerTime++;
                        handleFocus(x, y);
                    }
                }
            });
        } catch (Exception e) {
            Log.e(TAG, "autoFocus failer");
        }
    }

    private static Rect calculateTapArea(float x, float y, float coefficient, Context context) {
        float focusAreaSize = 300;
        int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();
        int centerX = (int) (x / ScreenUtils.getScreenWidth(context) * 2000 - 1000);
        int centerY = (int) (y / ScreenUtils.getScreenHeight(context) * 2000 - 1000);
        int left = clamp(centerX - areaSize / 2, -1000, 1000);
        int top = clamp(centerY - areaSize / 2, -1000, 1000);
        RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
        return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF
                .bottom));
    }

    private static int clamp(int x, int min, int max) {
        if (x > max) {
            return max;
        }
        if (x < min) {
            return min;
        }
        return x;
    }

    private void uploadLogData(Object data) {

        RetrofitManager.getInstance().createRequest(UserService.class)
                .uploadLogData(data)
                .enqueue(new Callback<CommonResult>() {
                    @Override
                    public void onResponse(Call<CommonResult> call, Response<CommonResult> response) {

                    }

                    @Override
                    public void onFailure(Call<CommonResult> call, Throwable t) {

                    }
                });
    }

    public class CompareSizesByArea implements Comparator<Camera.Size> {
        @Override
        public int compare(Camera.Size lhs, Camera.Size rhs) {
            return Long.signum((long) lhs.width * lhs.height -
                    (long) rhs.width * rhs.height);
        }
    }
}
